/**
* @file vpc_processor.cpp
*
* Copyright (c) Huawei Technologies Co., Ltd. 2024-2025. All rights reserved.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
#include "image_processor.h"

#include <set>
#include <atomic>
#include <memory>
#include <cstddef>
#include "securec.h"
#include "runtime/rt.h"
#include "utils/math_utils.h"
#include "common/log_inner.h"
#include "error_codes_inner.h"
#include "aicpu/dvpp/dvpp_def.h"
#include "aicpu/common/aicpu_task_struct.h"
#include "single_op/dvpp/common/dvpp_util.h"
#include "single_op/dvpp/mgr/dvpp_manager.h"

namespace acl {
    namespace dvpp {
    aclError ImageProcessor::acldvppVpcResizeAsync(acldvppChannelDesc *const channelDesc,
                                                   acldvppPicDesc *const inputDesc,
                                                   acldvppPicDesc *const outputDesc,
                                                   acldvppResizeConfig *const resizeConfig,
                                                   const aclrtStream stream) const
    {
        ACL_LOG_INFO("start to execute acldvppVpcResizeAsync");
        ACL_REQUIRES_NOT_NULL(channelDesc);
        ACL_REQUIRES_NOT_NULL(channelDesc->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL(inputDesc);
        ACL_REQUIRES_NOT_NULL(inputDesc->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL(outputDesc);
        ACL_REQUIRES_NOT_NULL(outputDesc->dataBuffer.data);
        if (channelDesc->isNeedNotify) {
            ACL_REQUIRES_NOT_NULL(channelDesc->notify);
        }

        // check vpc input format
        const aclError validResizeInputRet = ValidateVpcInputFormat(
                static_cast<acldvppPixelFormat>(inputDesc->dvppPicDesc.format));
        if (validResizeInputRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Verify][Format]input picture describe format verify failed, "
                                "result = %d, format = %u.", validResizeInputRet, inputDesc->dvppPicDesc.format);
            return validResizeInputRet;
        }

        // check vpc output format
        const aclError validResizeOutputRet = ValidateVpcOutputFormat(
                static_cast<acldvppPixelFormat>(outputDesc->dvppPicDesc.format));
        if (validResizeOutputRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Verify][Format]output picture describe format verify failed, "
                                "result = %d, format = %u.", validResizeOutputRet, outputDesc->dvppPicDesc.format);
            return validResizeOutputRet;
        }
        // check dvpp resize config
        const aclError validResizeConfigRet = ValidateDvppResizeConfig(resizeConfig);
        if (validResizeConfigRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Verify][ResizeConfig]resize config acldvppResizeConfig verify failed, "
                                "result = %d.", validResizeConfigRet);
            return validResizeConfigRet;
        }

        // CropAndPaste have 3 inputs
        constexpr uint32_t ioAddrNum = 3U;
        const size_t resizeConfigSize = CalDevDvppStructRealUsedSize(&resizeConfig->dvppResizeConfig);
        const size_t argsSize = sizeof(aicpu::AicpuParamHead) + (ioAddrNum * sizeof(uint64_t)) + resizeConfigSize;
        const std::unique_ptr<char_t[]> args(new (std::nothrow)char_t[argsSize]);
        ACL_REQUIRES_NOT_NULL(args);
        const auto paramHead = reinterpret_cast<aicpu::AicpuParamHead *>(args.get());
        paramHead->length = static_cast<uint32_t>(argsSize);
        paramHead->ioAddrNum = ioAddrNum;
        const auto ioAddr = reinterpret_cast<uint64_t *>(args.get() + sizeof(aicpu::AicpuParamHead));
        ioAddr[0] = reinterpret_cast<uintptr_t>(channelDesc->dataBuffer.data);
        ioAddr[1] = reinterpret_cast<uintptr_t>(inputDesc->dataBuffer.data);
        ioAddr[2] = reinterpret_cast<uintptr_t>(outputDesc->dataBuffer.data);
        constexpr size_t configOffset = sizeof(aicpu::AicpuParamHead) + (ioAddrNum * sizeof(uint64_t));
        const auto memcpyRet = memcpy_s(args.get() + configOffset, (argsSize - configOffset),
                                        &(resizeConfig->dvppResizeConfig), resizeConfigSize);
        if (memcpyRet != EOK) {
            ACL_LOG_INNER_ERROR("[Copy][Mem]copy resize config to args failed, result = %d.", memcpyRet);
            return ACL_ERROR_FAILURE;
        }

        if (aclRunMode_ == ACL_HOST) {
            aclError cpyRet = CopyDvppPicDescAsync(inputDesc, ACL_MEMCPY_HOST_TO_DEVICE, stream);
            if (cpyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][PicDesc]copy resize input picture desc failed, "
                                    "result = %d.", cpyRet);
                return cpyRet;
            }
            cpyRet = CopyDvppPicDescAsync(outputDesc, ACL_MEMCPY_HOST_TO_DEVICE, stream);
            if (cpyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][PicDesc]copy resize output picture desc to device failed, "
                                    "result = %d.", cpyRet);
                return cpyRet;
            }
        }

        const aclError launchRet = LaunchDvppTask(channelDesc, args.get(), static_cast<uint32_t>(argsSize),
                                                  acl::dvpp::DVPP_KERNELNAME_RESIZE, stream);
        if (launchRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Launch][DvppTask]launch dvpp task failed, errorCode = %d.", launchRet);
            return launchRet;
        }

        if (aclRunMode_ == ACL_HOST) {
            const aclError cpyRet = CopyDvppPicDescAsync(outputDesc, ACL_MEMCPY_DEVICE_TO_HOST, stream);
            if (cpyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][PicDesc]copy resize output pic desc from device failed, "
                                    "result = %d.", cpyRet);
                return cpyRet;
            }
        }

        ACL_LOG_INFO("Launch vpc resize tasks success");
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::ValidateParamForDvppVpcCropResizePaste(const acldvppChannelDesc *const channelDesc,
                                                                    const acldvppPicDesc *const inputDesc,
                                                                    const acldvppPicDesc *const outputDesc,
                                                                    const acldvppRoiConfig *const cropArea,
                                                                    const acldvppRoiConfig *const pasteArea,
                                                                    const bool pasteAreaSwitch,
                                                                    const acldvppResizeConfig *const resizeConfig,
                                                                    const bool resizeConfigSwitch,
                                                                    uint32_t &resizeConfigSize) const
    {
        ACL_REQUIRES_NOT_NULL(channelDesc);
        ACL_REQUIRES_NOT_NULL(channelDesc->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL(inputDesc);
        ACL_REQUIRES_NOT_NULL(inputDesc->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL(outputDesc);
        ACL_REQUIRES_NOT_NULL(outputDesc->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL(cropArea);
        if (pasteAreaSwitch) {
            ACL_REQUIRES_NOT_NULL(pasteArea);
        }
        if (channelDesc->isNeedNotify) {
            ACL_REQUIRES_NOT_NULL(channelDesc->notify);
        }

        if (resizeConfigSwitch) {
            ACL_REQUIRES_NOT_NULL(resizeConfig);
            const aclError validResizeConfigRet = ValidateDvppResizeConfig(resizeConfig);
            if (validResizeConfigRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Verify][DvppResizeConfig]resize config acldvppResizeConfig "
                                    "verify failed, errorCode = %d.", validResizeConfigRet);
                return validResizeConfigRet;
            }
            resizeConfigSize = static_cast<uint32_t>(CalDevDvppStructRealUsedSize(&resizeConfig->dvppResizeConfig));
        }

        // check vpc input format
        const aclError validCropInputRet = ValidateVpcInputFormat(
                static_cast<acldvppPixelFormat>(inputDesc->dvppPicDesc.format));
        if (validCropInputRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Verify][VpcInputFormat]input acldvppPicDesc format verify failed, "
                                "result = %d, format = %u.", validCropInputRet, inputDesc->dvppPicDesc.format);
            return validCropInputRet;
        }

        // check vpc output format
        const aclError validCropOutputRet = ValidateVpcOutputFormat(
                static_cast<acldvppPixelFormat>(outputDesc->dvppPicDesc.format));
        if (validCropOutputRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Verify][VpcOutputFormat]output acldvppPicDesc format verify failed,"
                                "result = %d, format = %u.", validCropOutputRet, outputDesc->dvppPicDesc.format);
            return validCropOutputRet;
        }
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::DvppVpcCropResizeAsync(const acldvppChannelDesc *const channelDesc,
                                                    const acldvppPicDesc *const inputDesc,
                                                    const acldvppPicDesc *const outputDesc,
                                                    const acldvppRoiConfig *const cropArea,
                                                    acldvppResizeConfig *const resizeConfig,
                                                    const bool resizeConfigSwitch,
                                                    const aclrtStream stream) const
    {
        uint32_t resizeConfigSize = 0U;
        const aclError validateRet = ValidateParamForDvppVpcCropResizePaste(channelDesc, inputDesc, outputDesc,
                                                                            cropArea, nullptr, false, resizeConfig, resizeConfigSwitch, resizeConfigSize);
        if (validateRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Verify][Param]verify params for DvppVpcCropResize failed, ret = %d", validateRet);
            return validateRet;
        }
        // CropAndPaste have 3 inputs
        constexpr uint32_t ioAddrNum = 3U;
        constexpr size_t roiConfigSize = sizeof(aicpu::dvpp::DvppRoiConfig);
        const size_t argsSize = sizeof(aicpu::AicpuParamHead) + (ioAddrNum * sizeof(uint64_t)) + roiConfigSize +
                                resizeConfigSize;
        const std::unique_ptr<char_t[]> args(new (std::nothrow)char_t[argsSize]);
        ACL_REQUIRES_NOT_NULL(args);
        const auto cpuParamHead = reinterpret_cast<aicpu::AicpuParamHead *>(args.get());
        cpuParamHead->length = static_cast<uint32_t>(argsSize);
        cpuParamHead->ioAddrNum = ioAddrNum;
        const auto ioAddr = reinterpret_cast<uint64_t *>(args.get() + sizeof(aicpu::AicpuParamHead));
        ioAddr[0] = reinterpret_cast<uintptr_t>(channelDesc->dataBuffer.data);
        ioAddr[1] = reinterpret_cast<uintptr_t>(inputDesc->dataBuffer.data);
        ioAddr[2] = reinterpret_cast<uintptr_t>(outputDesc->dataBuffer.data);

        // copy roi config
        constexpr size_t cropAreaOffset = sizeof(aicpu::AicpuParamHead) + (ioAddrNum * sizeof(uint64_t));
        auto cpyRet = memcpy_s(args.get() + cropAreaOffset, (argsSize - cropAreaOffset),
                               &(cropArea->dvppRoiConfig), roiConfigSize);
        if (cpyRet != EOK) {
            ACL_LOG_INNER_ERROR("[Copy][CropArea]copy crop area to args failed, result = %d.", cpyRet);
            return ACL_ERROR_FAILURE;
        }

        if (aclRunMode_ == ACL_HOST) {
            aclError copyRet = CopyDvppPicDescAsync(inputDesc, ACL_MEMCPY_HOST_TO_DEVICE, stream);
            if (copyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][PicDesc]copy input pic desc to device failed, errorCode = %d.", copyRet);
                return copyRet;
            }

            copyRet = CopyDvppPicDescAsync(outputDesc, ACL_MEMCPY_HOST_TO_DEVICE, stream);
            if (copyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][PicDesc]copy output pic desc to device failed, errorCode = %d.", copyRet);
                return copyRet;
            }
        }
        const char_t *kernelName = acl::dvpp::DVPP_KERNELNAME_CROP;
        // copy resize config
        if (resizeConfigSwitch) {
            constexpr size_t resizeConfigOffset = cropAreaOffset + roiConfigSize;
            cpyRet = memcpy_s(args.get() + resizeConfigOffset, (argsSize - resizeConfigOffset),
                              &(resizeConfig->dvppResizeConfig), static_cast<size_t>(resizeConfigSize));
            if (cpyRet != EOK) {
                ACL_LOG_INNER_ERROR("[Cpoy][ResizeConfig]copy resize config to args failed, result = %d.", cpyRet);
                return ACL_ERROR_FAILURE;
            }
            kernelName = acl::dvpp::DVPP_KERNELNAME_CROP_RESIZE;
        }
        const aclError launchRet = LaunchDvppTask(channelDesc, args.get(), static_cast<uint32_t>(argsSize),
                                                  kernelName, stream);
        if (launchRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Launch][Task]launch dvpp task failed, errorCode = %d.", launchRet);
            return launchRet;
        }

        if (aclRunMode_ == ACL_HOST) {
            const aclError copyRet = CopyDvppPicDescAsync(outputDesc, ACL_MEMCPY_DEVICE_TO_HOST, stream);
            if (copyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][PicDesc]copy output pic desc from device failed, errorCode = %d.",
                                    copyRet);
                return copyRet;
            }
        }
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::acldvppVpcCropResizeAsync(acldvppChannelDesc *const channelDesc,
                                                       acldvppPicDesc *const inputDesc,
                                                       acldvppPicDesc *const outputDesc,
                                                       acldvppRoiConfig *const cropArea,
                                                       acldvppResizeConfig *const resizeConfig,
                                                       const aclrtStream stream)
    {
        ACL_LOG_INFO("start to execute acldvppVpcCropResizeAsync");
        const auto ret = DvppVpcCropResizeAsync(channelDesc, inputDesc, outputDesc, cropArea,
                                                resizeConfig, true, stream);
        if (ret != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Exec][DvppVpcCropResizeAsync]execute acldvppVpcCropResizeAsync failed, "
                                "result = %d.", ret);
            return ret;
        }
        ACL_LOG_INFO("Launch vpc crop and resize tasks success");
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::acldvppVpcCropAsync(acldvppChannelDesc *const channelDesc,
                                                 acldvppPicDesc *const inputDesc,
                                                 acldvppPicDesc *const outputDesc,
                                                 acldvppRoiConfig *const cropArea,
                                                 const aclrtStream stream)
    {
        ACL_LOG_INFO("start to execute acldvppVpcCropAsync");
        const auto ret = DvppVpcCropResizeAsync(channelDesc, inputDesc, outputDesc, cropArea, nullptr, false, stream);
        if (ret != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Exec][DvppVpcCrop]execute acldvppVpcCropAsync failed, errorCode = %d.", ret);
            return ret;
        }
        ACL_LOG_INFO("Launch vpc crop tasks success");
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::DvppVpcBatchCropResizeAsync(const acldvppChannelDesc *const channelDesc,
                                                         acldvppBatchPicDesc *const srcBatchPicDescs,
                                                         const uint32_t *const roiNums,
                                                         const uint32_t size,
                                                         acldvppBatchPicDesc *const dstBatchPicDescs,
                                                         acldvppRoiConfig *cropAreas[],
                                                         acldvppResizeConfig *const resizeConfig,
                                                         const bool resizeConfigSwitch,
                                                         const aclrtStream stream) const
    {
        ACL_REQUIRES_NOT_NULL(channelDesc);
        ACL_REQUIRES_NOT_NULL(channelDesc->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL(srcBatchPicDescs);
        ACL_REQUIRES_NOT_NULL(srcBatchPicDescs->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL(dstBatchPicDescs);
        ACL_REQUIRES_NOT_NULL(dstBatchPicDescs->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL(cropAreas);
        ACL_REQUIRES_NOT_NULL(roiNums);
        ACL_REQUIRES_POSITIVE(size);
        if (channelDesc->isNeedNotify) {
            ACL_REQUIRES_NOT_NULL(channelDesc->notify);
        }

        if (resizeConfigSwitch) {
            ACL_REQUIRES_NOT_NULL(resizeConfig);
        }

        // valid input param
        const std::unique_ptr<uint16_t[]> roiNumsPtr(new (std::nothrow)uint16_t[size]);
        if (roiNumsPtr == nullptr) {
            ACL_LOG_INNER_ERROR("[Create][BatchCrop]create batch crop roiNums pointer failed, "
                                "roiNums size = %u.", size);
            return ACL_ERROR_INVALID_PARAM;
        }
        uint32_t totalRoiNums = 0U;
        const aclError validParamRet = ValidateAndConvertVpcBatchParams(srcBatchPicDescs,
                                                                        dstBatchPicDescs,
                                                                        roiNums,
                                                                        size,
                                                                        roiNumsPtr.get(),
                                                                        totalRoiNums,
                                                                        BATCH_ROI_MAX_SIZE,
                                                                        resizeConfig);
        if (validParamRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Verify][CropParam]verify batch crop param failed, errorCode = %d.", validParamRet);
            return validParamRet;
        }

        if (aclRunMode_ == ACL_HOST) {
            // copy input batch pic desc data
            aclError cpyAsyncRet = CopyDvppBatchPicDescAsync(srcBatchPicDescs,
                                                             ACL_MEMCPY_HOST_TO_DEVICE,
                                                             size,
                                                             stream);
            if (cpyAsyncRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][BatchPicDesc]async copy input batch pic desc to device failed, "
                                    "result = %d.", cpyAsyncRet);
                return cpyAsyncRet;
            }

            // copy output batch pic desc data
            cpyAsyncRet = CopyDvppBatchPicDescAsync(dstBatchPicDescs,
                                                    ACL_MEMCPY_HOST_TO_DEVICE,
                                                    totalRoiNums,
                                                    stream);
            if (cpyAsyncRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][BatchPicDesc]async copy output batch pic desc to device failed, "
                                    "result = %d.", cpyAsyncRet);
                return cpyAsyncRet;
            }
        } else {
            // set data buffer for input batch pic desc
            aclError setDataRet = SetDataBufferForBatchPicDesc(srcBatchPicDescs, size);
            if (setDataRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Set][DataBuffer]dvpp batch crop set data buffer for src batch pic desc "
                                    "failed, errorCode = %d.", setDataRet);
                return setDataRet;
            }

            setDataRet = SetDataBufferForBatchPicDesc(dstBatchPicDescs, totalRoiNums);
            if (setDataRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Set][DataBuffer]dvpp batch crop set data buffer for dst batch pic desc "
                                    "failed, errorCode = %d.", setDataRet);
                return setDataRet;
            }
        }

        void *const roiNumsAddress = static_cast<void *>(roiNumsPtr.get());
        const VpcBatchParams batchParams = {srcBatchPicDescs, dstBatchPicDescs, cropAreas, nullptr, totalRoiNums,
                                            roiNumsAddress, size};

        // launch task
        const aclError launchTaskRet = LaunchTaskForVpcBatchCrop(channelDesc, batchParams, resizeConfig, stream);
        if (launchTaskRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Launch][Task]launch task for vpc batch crop failed, errorCode = %d.", launchTaskRet);
            return launchTaskRet;
        }

        if (aclRunMode_ == ACL_HOST) {
            // copy output data
            const aclError validCpyRet = CopyDvppBatchPicDescAsync(dstBatchPicDescs,
                                                                   ACL_MEMCPY_DEVICE_TO_HOST,
                                                                   totalRoiNums,
                                                                   stream);
            if (validCpyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][BatchPicDesc]copy output batch pic desc to host failed, "
                                    "result = %d.", validCpyRet);
                return validCpyRet;
            }
        }
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::acldvppVpcBatchCropResizeAsync(acldvppChannelDesc *const channelDesc,
                                                            acldvppBatchPicDesc *const srcBatchPicDescs,
                                                            uint32_t *const roiNums,
                                                            const uint32_t size,
                                                            acldvppBatchPicDesc *const dstBatchPicDescs,
                                                            acldvppRoiConfig *cropAreas[],
                                                            acldvppResizeConfig *const resizeConfig,
                                                            const aclrtStream stream)
    {
        ACL_LOG_INFO("start to execute acldvppVpcBatchCropResizeAsync");
        const auto ret = DvppVpcBatchCropResizeAsync(channelDesc, srcBatchPicDescs, roiNums, size, dstBatchPicDescs,
                                                     cropAreas, resizeConfig, true, stream);
        if (ret != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Exec][BatchCropResize]execute acldvppVpcBatchCropResizeAsync failed, "
                                "result = %d.", ret);
            return ret;
        }
        ACL_LOG_INFO("Launch vpc batch crop and resize tasks success");
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::acldvppVpcBatchCropAsync(acldvppChannelDesc *const channelDesc,
                                                      acldvppBatchPicDesc *const srcBatchPicDescs,
                                                      uint32_t *const roiNums,
                                                      const uint32_t size,
                                                      acldvppBatchPicDesc *const dstBatchPicDescs,
                                                      acldvppRoiConfig *cropAreas[],
                                                      const aclrtStream stream)
    {
        ACL_LOG_INFO("start to execute acldvppVpcBatchCropAsync.");
        const auto ret = DvppVpcBatchCropResizeAsync(channelDesc, srcBatchPicDescs, roiNums, size, dstBatchPicDescs,
                                                     cropAreas, nullptr, false, stream);
        if (ret != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Exec][BatchCrop]execute acldvppVpcBatchCropAsync failed, errorCode = %d.", ret);
            return ret;
        }
        ACL_LOG_INFO("Launch vpc batch crop tasks success");
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::DvppVpcCropResizePasteAsync(const acldvppChannelDesc *const channelDesc,
                                                         const acldvppPicDesc *const inputDesc,
                                                         const acldvppPicDesc *const outputDesc,
                                                         const acldvppRoiConfig *const cropArea,
                                                         const acldvppRoiConfig *const pasteArea,
                                                         acldvppResizeConfig *const resizeConfig,
                                                         const bool resizeConfigSwitch,
                                                         const aclrtStream stream) const
    {
        uint32_t resizeConfigSize = 0U;
        const aclError validateRet = ValidateParamForDvppVpcCropResizePaste(channelDesc, inputDesc, outputDesc,
                                                                            cropArea, pasteArea, true, resizeConfig, resizeConfigSwitch, resizeConfigSize);
        if (validateRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Verify][Params]verify params for DvppVpcCropResizePaste failed, "
                                "ret = %d", validateRet);
            return validateRet;
        }
        // CropAndPaste have 3 inputs
        constexpr uint32_t ioAddrNum = 3U;
        constexpr size_t cropAreaConfigSize = sizeof(aicpu::dvpp::DvppRoiConfig);
        constexpr size_t pasteAreaConfigSize = sizeof(aicpu::dvpp::DvppRoiConfig);
        const size_t argsSize = sizeof(aicpu::AicpuParamHead) + (ioAddrNum * sizeof(uint64_t)) + cropAreaConfigSize +
                                pasteAreaConfigSize + resizeConfigSize;
        const std::unique_ptr<char_t[]> args(new (std::nothrow)char_t[argsSize]);
        ACL_REQUIRES_NOT_NULL(args);
        const auto paramHead = reinterpret_cast<aicpu::AicpuParamHead *>(args.get());
        paramHead->length = static_cast<uint32_t>(argsSize);
        paramHead->ioAddrNum = ioAddrNum;
        const auto ioAddr = reinterpret_cast<uint64_t *>(args.get() + sizeof(aicpu::AicpuParamHead));
        ioAddr[0] = reinterpret_cast<uintptr_t>(channelDesc->dataBuffer.data);
        ioAddr[1] = reinterpret_cast<uintptr_t>(inputDesc->dataBuffer.data);
        ioAddr[2] = reinterpret_cast<uintptr_t>(outputDesc->dataBuffer.data);

        constexpr size_t cropAreaOffset = sizeof(aicpu::AicpuParamHead) + (ioAddrNum * sizeof(uint64_t));
        auto memcpyRet = memcpy_s(args.get() + cropAreaOffset, (argsSize - cropAreaOffset),
                                  &(cropArea->dvppRoiConfig), cropAreaConfigSize);
        if (memcpyRet != EOK) {
            ACL_LOG_INNER_ERROR("[Copy][Area]copy crop area to args failed, result = %d.", memcpyRet);
            return ACL_ERROR_FAILURE;
        }

        constexpr size_t pasteAreaOffset = cropAreaOffset + cropAreaConfigSize;
        memcpyRet = memcpy_s(args.get() + pasteAreaOffset, (argsSize - pasteAreaOffset),
                             &(pasteArea->dvppRoiConfig), pasteAreaConfigSize);
        if (memcpyRet != EOK) {
            ACL_LOG_INNER_ERROR("[Copy][Area]copy paste area to args failed, result = %d.", memcpyRet);
            return ACL_ERROR_FAILURE;
        }

        if (resizeConfigSwitch) {
            constexpr const size_t resizeConfigOffset = pasteAreaOffset + pasteAreaConfigSize;
            memcpyRet = memcpy_s(args.get() + resizeConfigOffset, (argsSize - resizeConfigOffset),
                                 &(resizeConfig->dvppResizeConfig), static_cast<size_t>(resizeConfigSize));
            if (memcpyRet != EOK) {
                ACL_LOG_INNER_ERROR("[Copy][ResizeConfig]copy resize config to args failed, result = %d.", memcpyRet);
                return ACL_ERROR_FAILURE;
            }
        }

        if (aclRunMode_ == ACL_HOST) {
            aclError cpyRet = CopyDvppPicDescAsync(inputDesc, ACL_MEMCPY_HOST_TO_DEVICE, stream);
            if (cpyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][PicDesc]copy input pic desc to device failed, errorCode = %d.", cpyRet);
                return cpyRet;
            }

            cpyRet = CopyDvppPicDescAsync(outputDesc, ACL_MEMCPY_HOST_TO_DEVICE, stream);
            if (cpyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][PicDesc]copy output pic desc to device failed, errorCode = %d.", cpyRet);
                return cpyRet;
            }
        }
        const char_t *kernelName = acl::dvpp::DVPP_KERNELNAME_CROP_AND_PASTE;
        if (resizeConfigSwitch) {
            kernelName = acl::dvpp::DVPP_KERNELNAME_CROP_RESIZE_PASTE;
        }
        const aclError launchRet = LaunchDvppTask(channelDesc, args.get(), static_cast<uint32_t>(argsSize),
                                                  kernelName, stream);
        if (launchRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Launch][Task]launch dvpp task failed, errorCode = %d.", launchRet);
            return launchRet;
        }

        if (aclRunMode_ == ACL_HOST) {
            const aclError cpyRet = acl::dvpp::CopyDvppPicDescAsync(outputDesc, ACL_MEMCPY_DEVICE_TO_HOST, stream);
            if (cpyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][PicDesc]copy output pic desc from device failed, errorCode = %d.", cpyRet);
                return cpyRet;
            }
        }
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::acldvppVpcCropResizePasteAsync(acldvppChannelDesc *const channelDesc,
                                                            acldvppPicDesc *const inputDesc,
                                                            acldvppPicDesc *const outputDesc,
                                                            acldvppRoiConfig *const cropArea,
                                                            acldvppRoiConfig *const pasteArea,
                                                            acldvppResizeConfig *const resizeConfig,
                                                            const aclrtStream stream)
    {
        ACL_LOG_INFO("start to execute acldvppVpcCropResizePasteAsync.");
        const auto ret = DvppVpcCropResizePasteAsync(channelDesc, inputDesc, outputDesc, cropArea,
                                                     pasteArea, resizeConfig, true, stream);
        if (ret != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Exec][CropResizePaste]execute acldvppVpcCropResizePasteAsync "
                                "failed, errorCode = %d.", ret);
            return ret;
        }
        ACL_LOG_INFO("Launch vpc crop, resize and paste tasks success");
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::acldvppVpcCropAndPasteAsync(acldvppChannelDesc *const channelDesc,
                                                         acldvppPicDesc *const inputDesc,
                                                         acldvppPicDesc *const outputDesc,
                                                         acldvppRoiConfig *const cropArea,
                                                         acldvppRoiConfig *const pasteArea,
                                                         const aclrtStream stream)
    {
        ACL_LOG_INFO("start to execute acldvppVpcCropAndPasteAsync.");
        const auto ret = DvppVpcCropResizePasteAsync(channelDesc, inputDesc, outputDesc, cropArea,
                                                     pasteArea, nullptr, false, stream);
        if (ret != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Exec][CropAndPaste]execute acldvppVpcCropAndPasteAsync failed, errorCode = %d.",
                                ret);
            return ret;
        }
        ACL_LOG_INFO("Launch vpc crop and paste tasks success.");
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::DvppVpcBatchCropResizePasteAsync(const acldvppChannelDesc *const channelDesc,
                                                              acldvppBatchPicDesc *const srcBatchPicDescs,
                                                              const uint32_t *const roiNums,
                                                              const uint32_t size,
                                                              acldvppBatchPicDesc *const dstBatchPicDescs,
                                                              acldvppRoiConfig *cropAreas[],
                                                              acldvppRoiConfig *pasteAreas[],
                                                              acldvppResizeConfig *const resizeConfig,
                                                              const bool resizeConfigSwitch,
                                                              const aclrtStream stream) const
    {
        ACL_REQUIRES_NOT_NULL(channelDesc);
        ACL_REQUIRES_NOT_NULL(channelDesc->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL(srcBatchPicDescs);
        ACL_REQUIRES_NOT_NULL(srcBatchPicDescs->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL(dstBatchPicDescs);
        ACL_REQUIRES_NOT_NULL(dstBatchPicDescs->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL(cropAreas);
        ACL_REQUIRES_NOT_NULL(pasteAreas);
        ACL_REQUIRES_NOT_NULL(roiNums);
        ACL_REQUIRES_POSITIVE(size);
        if (channelDesc->isNeedNotify) {
            ACL_REQUIRES_NOT_NULL(channelDesc->notify);
        }

        if (resizeConfigSwitch) {
            ACL_REQUIRES_NOT_NULL(resizeConfig);
        }

        // valid input param
        const std::unique_ptr<uint16_t[]> devRoiNums(new (std::nothrow)uint16_t[size]);
        if (devRoiNums == nullptr) {
            ACL_LOG_INNER_ERROR("[Check][devRoiNums]create device roiNums failed, "
                                "roiNums size = %u.", size);
            return ACL_ERROR_INVALID_PARAM;
        }
        uint32_t totalRoiNums = 0U;
        const aclError validParamRet = ValidateAndConvertVpcBatchParams(srcBatchPicDescs,
                                                                        dstBatchPicDescs,
                                                                        roiNums,
                                                                        size,
                                                                        devRoiNums.get(),
                                                                        totalRoiNums,
                                                                        BATCH_ROI_MAX_SIZE,
                                                                        resizeConfig);
        if (validParamRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Check][ValidParam]verify batch crop and paste param failed, "
                                "result = %d.", validParamRet);
            return validParamRet;
        }

        if (aclRunMode_ == ACL_HOST) {
            // copy batch picDesc data
            aclError cpyRet = CopyDvppBatchPicDescAsync(srcBatchPicDescs,
                                                        ACL_MEMCPY_HOST_TO_DEVICE,
                                                        size,
                                                        stream);
            if (cpyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][BatchPicDesc]copy input batch pic desc to device failed, "
                                    "result = %d.", cpyRet);
                return cpyRet;
            }

            cpyRet = CopyDvppBatchPicDescAsync(dstBatchPicDescs,
                                               ACL_MEMCPY_HOST_TO_DEVICE,
                                               totalRoiNums,
                                               stream);
            if (cpyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][BatchPicDesc]copy output batch pic desc to device failed, "
                                    "result = %d.", cpyRet);
                return cpyRet;
            }
        } else {
            // set data buffer for input batch pic desc
            aclError setDataRet = SetDataBufferForBatchPicDesc(srcBatchPicDescs, size);
            if (setDataRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Set][DataBuffer]set data buffer for src batch pic desc failed, "
                                    "result = %d.", setDataRet);
                return setDataRet;
            }

            setDataRet = SetDataBufferForBatchPicDesc(dstBatchPicDescs, totalRoiNums);
            if (setDataRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Set][DataBuffer]set data buffer for dst batch pic desc failed, "
                                    "result = %d.", setDataRet);
                return setDataRet;
            }
        }

        void *const roiNumsAddr = static_cast<void *>(devRoiNums.get());
        const VpcBatchParams batchParams = {srcBatchPicDescs,
                                            dstBatchPicDescs,
                                            cropAreas,
                                            pasteAreas,
                                            totalRoiNums,
                                            roiNumsAddr,
                                            size};

        // launch task
        const aclError launchTaskRet = LaunchTaskForVpcBatchCropAndPaste(channelDesc,
                                                                         batchParams, resizeConfig, stream);
        if (launchTaskRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Launch][Task]launch task for vpc batch crop and paste failed, "
                                "result = %d.", launchTaskRet);
            return launchTaskRet;
        }

        if (aclRunMode_ == ACL_HOST) {
            // copy output data
            const aclError cpyRet = acl::dvpp::CopyDvppBatchPicDescAsync(dstBatchPicDescs,
                                                                         ACL_MEMCPY_DEVICE_TO_HOST,
                                                                         totalRoiNums,
                                                                         stream);
            if (cpyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][BatchPicDesc]copy output batch pic desc to host failed, "
                                    "result = %d.", cpyRet);
                return cpyRet;
            }
        }
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::acldvppVpcBatchCropResizePasteAsync(acldvppChannelDesc *const channelDesc,
                                                                 acldvppBatchPicDesc *const srcBatchPicDescs,
                                                                 uint32_t *const roiNums,
                                                                 const uint32_t size,
                                                                 acldvppBatchPicDesc *const dstBatchPicDescs,
                                                                 acldvppRoiConfig *cropAreas[],
                                                                 acldvppRoiConfig *pasteAreas[],
                                                                 acldvppResizeConfig *const resizeConfig,
                                                                 const aclrtStream stream)
    {
        ACL_LOG_INFO("start to execute acldvppVpcBatchCropResizePasteAsync.");
        const auto ret = DvppVpcBatchCropResizePasteAsync(channelDesc, srcBatchPicDescs,
                                                          roiNums, size, dstBatchPicDescs,
                                                          cropAreas, pasteAreas, resizeConfig, true, stream);
        if (ret != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Exec][BatchCropResizePaste]execute acldvppVpcBatchCropResizePasteAsync failed, "
                                "result = %d.", ret);
            return ret;
        }
        ACL_LOG_INFO("Launch vpc batch crop, resize and paste tasks success");
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::acldvppVpcBatchCropAndPasteAsync(acldvppChannelDesc *const channelDesc,
                                                              acldvppBatchPicDesc *const srcBatchPicDescs,
                                                              uint32_t *const roiNums,
                                                              const uint32_t size,
                                                              acldvppBatchPicDesc *const dstBatchPicDescs,
                                                              acldvppRoiConfig *cropAreas[],
                                                              acldvppRoiConfig *pasteAreas[],
                                                              const aclrtStream stream)
    {
        // validate parametes
        ACL_LOG_INFO("start to execute acldvppVpcBatchCropAndPasteAsync.");
        const auto ret = DvppVpcBatchCropResizePasteAsync(channelDesc, srcBatchPicDescs, roiNums, size,
                                                          dstBatchPicDescs, cropAreas, pasteAreas, nullptr, false, stream);
        if (ret != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Exec][BatchCropAndPaste]execute acldvppVpcBatchCropAndPasteAsync failed, "
                                "result = %d.", ret);
            return ret;
        }
        ACL_LOG_INFO("Launch vpc batch crop and paste tasks success");
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::acldvppVpcConvertColorAsync(acldvppChannelDesc *const channelDesc,
                                                         acldvppPicDesc *const inputDesc,
                                                         acldvppPicDesc *const outputDesc,
                                                         const aclrtStream stream) const
    {
        (void)(channelDesc);
        (void)(inputDesc);
        (void)(outputDesc);
        (void)(stream);
        ACL_LOG_ERROR("[Unsupport][Version]This version can not support vpc convert color api. Please check.");
        const char_t *argList[] = {"feature", "reason"};
        const char_t *argVal[] = {"vpc convert color api", "Please check"};
        acl::AclErrorLogManager::ReportInputErrorWithChar(acl::UNSUPPORTED_FEATURE_MSG,
                                                          argList, argVal, 2U);
        return ACL_ERROR_FEATURE_UNSUPPORTED;
    }

    aclError ImageProcessor::acldvppVpcPyrDownAsync(acldvppChannelDesc *const channelDesc,
                                                    acldvppPicDesc *const inputDesc,
                                                    acldvppPicDesc *const outputDesc,
                                                    void* const reserve,
                                                    const aclrtStream stream) const
    {
        (void)(channelDesc);
        (void)(inputDesc);
        (void)(outputDesc);
        (void)(reserve);
        (void)(stream);
        ACL_LOG_ERROR("[Unsupport][Version]This version can not support vpc pyramid down api. Please check.");
        const char_t *argList[] = {"feature", "reason"};
        const char_t *argVal[] = {"vpc pyramid down api", "please check"};
        acl::AclErrorLogManager::ReportInputErrorWithChar(acl::UNSUPPORTED_FEATURE_MSG,
                                                          argList, argVal, 2U);
        return ACL_ERROR_FEATURE_UNSUPPORTED;
    }

    aclError ImageProcessor::acldvppVpcEqualizeHistAsync(const acldvppChannelDesc *const channelDesc,
                                                         const acldvppPicDesc *const inputDesc,
                                                         acldvppPicDesc *const outputDesc,
                                                         const acldvppLutMap *const lutMap,
                                                         const aclrtStream stream) const
    {
        (void)(channelDesc);
        (void)(inputDesc);
        (void)(outputDesc);
        (void)(lutMap);
        (void)(stream);
        ACL_LOG_ERROR("[Unsupport][Version]This version can not support vpc equalize "
                      "hist api. Please check.");
        const char_t *argList[] = {"feature", "reason"};
        const char_t *argVal[] = {"vpc equalize hist api", "please check"};
        acl::AclErrorLogManager::ReportInputErrorWithChar(acl::UNSUPPORTED_FEATURE_MSG,
                                                          argList, argVal, 2U);
        return ACL_ERROR_FEATURE_UNSUPPORTED;
    }

    aclError ImageProcessor::acldvppVpcMakeBorderAsync(const acldvppChannelDesc *const channelDesc,
                                                       const acldvppPicDesc *const inputDesc,
                                                       acldvppPicDesc *const outputDesc,
                                                       const acldvppBorderConfig *const borderConfig,
                                                       const aclrtStream stream) const
    {
        (void)(channelDesc);
        (void)(inputDesc);
        (void)(outputDesc);
        (void)(borderConfig);
        (void)(stream);
        ACL_LOG_ERROR("[Unsupport][Version]This version can not support "
                      "vpc make border api. Please check.");
        const char_t *argList[] = {"feature", "reason"};
        const char_t *argVal[] = {"vpc make border api", "please check"};
        acl::AclErrorLogManager::ReportInputErrorWithChar(acl::UNSUPPORTED_FEATURE_MSG,
                                                          argList, argVal, 2U);
        return ACL_ERROR_FEATURE_UNSUPPORTED;
    }

    aclError ImageProcessor::acldvppVpcBatchCropResizeMakeBorderAsync(acldvppChannelDesc *const channelDesc,
                                                                      acldvppBatchPicDesc *const srcBatchPicDescs,
                                                                      uint32_t *const roiNums,
                                                                      const uint32_t size,
                                                                      acldvppBatchPicDesc *const dstBatchPicDescs,
                                                                      acldvppRoiConfig *cropAreas[],
                                                                      acldvppBorderConfig *borderCfgs[],
                                                                      acldvppResizeConfig *const resizeConfig,
                                                                      const aclrtStream stream) const
    {
        (void)(channelDesc);
        (void)(srcBatchPicDescs);
        (void)(roiNums);
        (void)(size);
        (void)(dstBatchPicDescs);
        (void)(cropAreas);
        (void)(borderCfgs);
        (void)(resizeConfig);
        (void)(stream);
        ACL_LOG_ERROR("[Unsupport][Version]This version can not support "
                      "vpc batch crop, resize and make border api. Please check.");
        const char_t *argList[] = {"feature", "reason"};
        const char_t *argVal[] = {"vpc make border api", "please check"};
        acl::AclErrorLogManager::ReportInputErrorWithChar(acl::UNSUPPORTED_FEATURE_MSG,
                                                          argList, argVal, 2U);
        return ACL_ERROR_FEATURE_UNSUPPORTED;
    }

    aclError ImageProcessor::acldvppVpcCalcHistAsync(acldvppChannelDesc *const channelDesc,
                                                     acldvppPicDesc *const srcPicDesc,
                                                     acldvppHist *const hist,
                                                     void *const reserve,
                                                     const aclrtStream stream) const
    {
        (void)(channelDesc);
        (void)(srcPicDesc);
        (void)(hist);
        (void)(reserve);
        (void)(stream);
        ACL_LOG_ERROR("[Unsupport][Version]This version can not support vpc "
                      "calculate hist api. Please check.");
        const char_t *argList[] = {"feature", "reason"};
        const char_t *argVal[] = {"vpc calculate hist api", "please check"};
        acl::AclErrorLogManager::ReportInputErrorWithChar(acl::UNSUPPORTED_FEATURE_MSG,
                                                          argList, argVal, 2U);
        return ACL_ERROR_FEATURE_UNSUPPORTED;
    }

    acldvppHist* ImageProcessor::acldvppCreateHist() const
    {
        ACL_LOG_ERROR("[Unsupport][Version]This version can not support "
                      "vpc hist api. Please check.");
        const char_t *argList[] = {"feature", "reason"};
        const char_t *argVal[] = {"vpc hist api", "please check"};
        acl::AclErrorLogManager::ReportInputErrorWithChar(acl::UNSUPPORTED_FEATURE_MSG,
                                                          argList, argVal, 2U);
        return nullptr;
    }

    aclError ImageProcessor::acldvppDestroyHist(acldvppHist *const hist) const
    {
        (void)(hist);
        ACL_LOG_ERROR("[Unsupport][Version]This version can not support "
                      "vpc hist api. Please check.");
        const char_t *argList[] = {"feature", "reason"};
        const char_t *argVal[] = {"vpc hist api", "please check"};
        acl::AclErrorLogManager::ReportInputErrorWithChar(acl::UNSUPPORTED_FEATURE_MSG,
                                                          argList, argVal, 2U);
        return ACL_ERROR_FEATURE_UNSUPPORTED;
    }

    aclError ImageProcessor::acldvppClearHist(acldvppHist *const hist) const
    {
        (void)(hist);
        ACL_LOG_ERROR("[Unsupport][Version]This version can not support "
                      "vpc hist api. Please check.");
        const char_t *argList[] = {"feature", "reason"};
        const char_t *argVal[] = {"vpc hist api", "please check"};
        acl::AclErrorLogManager::ReportInputErrorWithChar(acl::UNSUPPORTED_FEATURE_MSG,
                                                          argList, argVal, 2U);
        return ACL_ERROR_FEATURE_UNSUPPORTED;
    }

    uint32_t ImageProcessor::acldvppGetHistDims(acldvppHist *const hist) const
    {
        (void)(hist);
        ACL_LOG_ERROR("[Unsupport][Version]This version can not support "
                      "vpc hist api. Please check.");
        const char_t *argList[] = {"feature", "reason"};
        const char_t *argVal[] = {"vpc hist api", "please check"};
        acl::AclErrorLogManager::ReportInputErrorWithChar(acl::UNSUPPORTED_FEATURE_MSG,
                                                          argList, argVal, 2U);
        return 0U;
    }

    aclError ImageProcessor::acldvppGetHistData(acldvppHist *const hist, const uint32_t dim,
                                                uint32_t **const data, uint16_t *const len) const
    {
        (void)(hist);
        (void)(dim);
        (void)(data);
        (void)(len);
        ACL_LOG_ERROR("[Unsupport][Version]This version can not support "
                      "vpc hist api. Please check.");
        const char_t *argList[] = {"feature", "reason"};
        const char_t *argVal[] = {"vpc hist api", "please check"};
        acl::AclErrorLogManager::ReportInputErrorWithChar(acl::UNSUPPORTED_FEATURE_MSG,
                                                          argList, argVal, 2U);
        return ACL_ERROR_FEATURE_UNSUPPORTED;
    }

    uint32_t ImageProcessor::acldvppGetHistRetCode(acldvppHist *const hist) const
    {
        (void)(hist);
        ACL_LOG_ERROR("[Unsupport][Version]This version can not support "
                      "vpc hist api. Please check.");
        const char_t *argList[] = {"feature", "reason"};
        const char_t *argVal[] = {"vpc hist api", "please check"};
        acl::AclErrorLogManager::ReportInputErrorWithChar(acl::UNSUPPORTED_FEATURE_MSG,
                                                          argList, argVal, 2U);
        return 0U;
    }

    aclError ImageProcessor::ValidateAndConvertVpcBatchParams(const acldvppBatchPicDesc *const srcBatchPicDescs,
                                                              const acldvppBatchPicDesc *const dstBatchPicDescs,
                                                              const uint32_t *const roiNums,
                                                              const uint32_t size,
                                                              uint16_t *const deviceRoiNums,
                                                              uint32_t &totalRoiNums,
                                                              const uint32_t maxRoiNums,
                                                              const acldvppResizeConfig *const resizeConfig) const
    {
        // valid size
        bool validParam = (size == 0U) || (srcBatchPicDescs->dvppBatchPicDescs.batchSize < size);
        if (validParam) {
            ACL_LOG_ERROR("[Check][BatchSize]srcBatchPicDescs batchSize less than roiNums size or size = 0, "
                          "batch size = %u, size = %u.", srcBatchPicDescs->dvppBatchPicDescs.batchSize, size);
            const std::string convertedStr = std::to_string(srcBatchPicDescs->dvppBatchPicDescs.batchSize);
            const std::string errMsg =
                    acl::AclErrorLogManager::FormatStr("less than roiNums size[%u] or size = 0", size);
            const char_t *argList[] = {"param", "value", "reason"};
            const char_t *argVal[] = {"srcBatchPicDescs batchSize", convertedStr.c_str(), errMsg.c_str()};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_PARAM_MSG,
                                                              argList, argVal, 3U);
            return ACL_ERROR_INVALID_PARAM;
        }

        if (resizeConfig != nullptr) {
            const aclError validResizeConfigRet = ValidateDvppResizeConfig(resizeConfig);
            if (validResizeConfigRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Check][ResizeConfig]resize config acldvppResizeConfig verify failed, "
                                    "result = %d.", validResizeConfigRet);
                return validResizeConfigRet;
            }
        }

        // validate input format
        aclError validFormat = ACL_SUCCESS;
        for (uint32_t idx = 0U; idx < srcBatchPicDescs->dvppBatchPicDescs.batchSize; ++idx) {
            validFormat = ValidateVpcInputFormat(
                    static_cast<acldvppPixelFormat>(srcBatchPicDescs->aclDvppPicDescs[idx].dvppPicDesc.format));
            if (validFormat != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Verify][InputFormat]input acldvppPicDesc format verify failed, "
                                    "result = %d, format = %u.", validFormat,
                                    srcBatchPicDescs->aclDvppPicDescs[idx].dvppPicDesc.format);
                return validFormat;
            }
        }

        // validate output format
        for (uint32_t idx = 0U; idx < dstBatchPicDescs->dvppBatchPicDescs.batchSize; ++idx) {
            validFormat = ValidateVpcOutputFormat(
                    static_cast<acldvppPixelFormat>(dstBatchPicDescs->aclDvppPicDescs[idx].dvppPicDesc.format));
            if (validFormat != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Verify][OutputFormat]output acldvppPicDesc format verify failed, "
                                    "result = %d, format = %u.", validFormat,
                                    dstBatchPicDescs->aclDvppPicDescs[idx].dvppPicDesc.format);
                return validFormat;
            }
        }

        // calculate roi nums
        for (uint32_t idx = 0U; idx < size; ++idx) {
            validParam = (roiNums[idx] > static_cast<uint32_t>(UINT16_MAX)) || (roiNums[idx] == 0U);
            if (validParam) {
                ACL_LOG_INNER_ERROR("[Check][Params]roiNums index[%u] great than UINT16_MAX[65535] or its value is %u",
                                    idx, roiNums[idx]);
                return ACL_ERROR_INVALID_PARAM;
            }
            deviceRoiNums[idx] = static_cast<uint16_t>(roiNums[idx]);
            totalRoiNums += roiNums[idx];
        }

        // validate total roi nums: min value is 1
        validParam = (totalRoiNums < 1U) || (totalRoiNums > maxRoiNums);
        if (validParam) {
            ACL_LOG_INNER_ERROR("[Check][Params]the value of totalRoiNums[%d] is invalid, "
                                "it must be between in [%d, %d]", totalRoiNums, 1, maxRoiNums);
            return ACL_ERROR_INVALID_PARAM;
        }
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::LaunchTaskForVpcBatchCrop(const acldvppChannelDesc *const channelDesc,
                                                       const VpcBatchParams &batchParams,
                                                       const acldvppResizeConfig *const resizeConfig,
                                                       const rtStream_t stream) const
    {
        // check corp area
        for (uint32_t idx = 0U; idx < batchParams.totalRoiNums_; ++idx) {
            ACL_REQUIRES_NOT_NULL(batchParams.cropAreas_[idx]);
        }

        // calculate crop config total size
        constexpr const uint32_t cropAreaSize = static_cast<uint32_t>(sizeof(aicpu::dvpp::DvppRoiConfig));
        const uint32_t totalCropConfigSize = cropAreaSize * batchParams.totalRoiNums_;
        size_t resizeConfigSize = 0U;
        if (resizeConfig != nullptr) {
            resizeConfigSize = CalDevDvppStructRealUsedSize(&resizeConfig->dvppResizeConfig);
        }

        // BatchCrop have 3 inputs
        constexpr uint32_t addrNum = 3U;
        const size_t argsSize = sizeof(aicpu::AicpuParamHead) + (addrNum * sizeof(uint64_t)) +
                                totalCropConfigSize + (batchParams.batchSize_ * sizeof(uint16_t)) + resizeConfigSize;
        const std::unique_ptr<char_t[]> args(new (std::nothrow)char_t[argsSize]);
        ACL_REQUIRES_NOT_NULL(args);
        const auto paramHead = reinterpret_cast<aicpu::AicpuParamHead *>(args.get());
        paramHead->length = static_cast<uint32_t>(argsSize);
        paramHead->ioAddrNum = addrNum;
        const auto ioAddr = reinterpret_cast<uint64_t *>(args.get() + sizeof(aicpu::AicpuParamHead));
        ioAddr[0] = reinterpret_cast<uintptr_t>(channelDesc->dataBuffer.data);
        ioAddr[1] = reinterpret_cast<uintptr_t>(batchParams.srcBatchPicDescs_->dataBuffer.data);
        ioAddr[2] = reinterpret_cast<uintptr_t>(batchParams.dstBatchPicDescs_->dataBuffer.data);

        size_t cropAreaOffset = sizeof(aicpu::AicpuParamHead) + (addrNum * sizeof(uint64_t));
        // copy crop config
        for (size_t idx = 0U; idx < batchParams.totalRoiNums_; ++idx) {
            const auto memcpyRet = memcpy_s(args.get() + cropAreaOffset, (argsSize - cropAreaOffset),
                                            &(batchParams.cropAreas_[idx]->dvppRoiConfig), cropAreaSize);
            ACL_REQUIRES_EOK(memcpyRet, memcpy_s);
            cropAreaOffset += cropAreaSize;
        }
        // copy roiNums
        auto memcpyRet = memcpy_s(args.get() + cropAreaOffset, (argsSize - cropAreaOffset),
                                  batchParams.roiNums_, sizeof(uint16_t) * batchParams.batchSize_);
        ACL_REQUIRES_EOK(memcpyRet, memcpy_s);

        // copy resize config
        const char_t *kernelName = acl::dvpp::DVPP_KERNELNAME_BATCH_CROP;
        if (resizeConfig != nullptr) {
            kernelName = acl::dvpp::DVPP_KERNELNAME_BATCH_CROP_RESIZE;
            cropAreaOffset += (sizeof(uint16_t) * batchParams.batchSize_);
            memcpyRet = memcpy_s(args.get() + cropAreaOffset, (argsSize - cropAreaOffset),
                                 &(resizeConfig->dvppResizeConfig), resizeConfigSize);
            ACL_REQUIRES_EOK(memcpyRet, memcpy_s);
        }
        return LaunchDvppTask(channelDesc, args.get(), static_cast<uint32_t>(argsSize), kernelName, stream);
    }

    aclError ImageProcessor::LaunchTaskForVpcBatchCropAndPaste(const acldvppChannelDesc *const channelDesc,
                                                               const VpcBatchParams &batchParams,
                                                               const acldvppResizeConfig *const resizeConfig,
                                                               const rtStream_t stream) const
    {
        // check crop area and paste area
        for (uint32_t idx = 0U; idx < batchParams.totalRoiNums_; ++idx) {
            ACL_REQUIRES_NOT_NULL(batchParams.cropAreas_[idx]);
            ACL_REQUIRES_NOT_NULL(batchParams.pasteAreas_[idx]);
        }
        // 2 areas: crop area and paste area
        constexpr size_t roiAreaSize = sizeof(aicpu::dvpp::DvppRoiConfig);
        const size_t totalRoiConfigSize = roiAreaSize * 2U * batchParams.totalRoiNums_;
        size_t resizeConfigSize = 0U;
        if (resizeConfig != nullptr) {
            resizeConfigSize = CalDevDvppStructRealUsedSize(&resizeConfig->dvppResizeConfig);
        }

        // BatchCropAndPaste have 3 inputs
        constexpr uint32_t ioAddrNum = 3U;
        const size_t argsSize = sizeof(aicpu::AicpuParamHead) + (ioAddrNum * sizeof(uint64_t)) + totalRoiConfigSize +
                                (batchParams.batchSize_ * sizeof(uint16_t)) + resizeConfigSize;
        const std::unique_ptr<char_t[]> args(new (std::nothrow)char_t[argsSize]);
        ACL_REQUIRES_NOT_NULL(args);
        const auto paramHead = reinterpret_cast<aicpu::AicpuParamHead *>(args.get());
        paramHead->length = static_cast<uint32_t>(argsSize);
        paramHead->ioAddrNum = ioAddrNum;
        const auto ioAddr = reinterpret_cast<uint64_t *>(args.get() + sizeof(aicpu::AicpuParamHead));
        ioAddr[0] = reinterpret_cast<uintptr_t>(channelDesc->dataBuffer.data);
        ioAddr[1] = reinterpret_cast<uintptr_t>(batchParams.srcBatchPicDescs_->dataBuffer.data);
        ioAddr[2] = reinterpret_cast<uintptr_t>(batchParams.dstBatchPicDescs_->dataBuffer.data);

        size_t roiAreaOffset = sizeof(aicpu::AicpuParamHead) + (ioAddrNum * sizeof(uint64_t));
        // copy crop config
        for (uint32_t idx = 0U; idx < batchParams.totalRoiNums_; ++idx) {
            auto memcpyRet = memcpy_s(args.get() + roiAreaOffset, (argsSize - roiAreaOffset),
                                      &(batchParams.cropAreas_[idx]->dvppRoiConfig), roiAreaSize);
            if (memcpyRet != EOK) {
                ACL_LOG_INNER_ERROR("[Copy][CropArea]copy crop area to args failed, result = %d.", memcpyRet);
                return ACL_ERROR_FAILURE;
            }
            roiAreaOffset += roiAreaSize;

            memcpyRet = memcpy_s(args.get() + roiAreaOffset, (argsSize - roiAreaOffset),
                                 &(batchParams.pasteAreas_[idx]->dvppRoiConfig), roiAreaSize);
            if (memcpyRet != EOK) {
                ACL_LOG_INNER_ERROR("[Copy][PasteArea]copy paste area to args failed, result = %d.", memcpyRet);
                return ACL_ERROR_FAILURE;
            }
            roiAreaOffset += roiAreaSize;
        }
        // copy roiNums
        auto memcpyRet = memcpy_s(args.get() + roiAreaOffset, (argsSize - roiAreaOffset),
                                  batchParams.roiNums_, sizeof(uint16_t) * batchParams.batchSize_);
        if (memcpyRet != EOK) {
            ACL_LOG_INNER_ERROR("[Copy][RoiNums]copy roiNums to args failed, result = %d.", memcpyRet);
            return ACL_ERROR_FAILURE;
        }

        // copy resize config
        const char_t *kernelName = acl::dvpp::DVPP_KERNELNAME_BATCH_CROP_AND_PASTE;
        if (resizeConfig != nullptr) {
            const size_t resizeConfigOffset = roiAreaOffset + (sizeof(uint16_t) * batchParams.batchSize_);
            memcpyRet = memcpy_s(args.get() + resizeConfigOffset, (argsSize - resizeConfigOffset),
                                 &(resizeConfig->dvppResizeConfig), resizeConfigSize);
            if (memcpyRet != EOK) {
                ACL_LOG_INNER_ERROR("[Copy][ResizeConfig]copy resize config to args failed, "
                                    "result = %d.", memcpyRet);
                return ACL_ERROR_FAILURE;
            }
            kernelName = acl::dvpp::DVPP_KERNELNAME_BATCH_CROP_RESIZE_PASTE;
        }

        const aclError launchRet = LaunchDvppTask(channelDesc, args.get(), static_cast<uint32_t>(argsSize),
                                                  kernelName, stream);
        if (launchRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Launch][Task]launch dvpp task failed, errorCode = %d.", launchRet);
            return launchRet;
        }
        return ACL_SUCCESS;
    }
    }
}
